#pragma once

#include "noncopyable.h"
#include "EventLoop.h"
#include "Timestamp.h"

#include <functional>
#include <memory>

/**
 * 回调函数是被传递到其他函数或方法中的函数，当某个特定事件或条件发生时，它会被调用。
 * 回调函数使得代码具有更好的模块化，提高了代码的可复用性，并使得程序能够以更响应式的方式处理事件。
 */
/**
 * 理清楚EventLoop、Channel、Poller之间的关系 《=Reactor模型上对应Demultiplex，即多路事件分发器
 * Channel可以理解为通道，封装了sockfd和其感兴趣的event,如EPOLLIN、EPOLLOUT事件
 * 还绑定了Poller返回的具体事件
 */
/**
 * 循环依赖：最常见的情况是循环依赖。当两个或多个类互相引用对方时，比如 ClassA 引用 ClassB，同时 ClassB 又引用 ClassA。
 * 在这种情况下，即使包含了对方的头文件，编译器在编译某个类的定义之前可能还没有看到另一个类的完整定义。
 * 前置声明可以在这种情况下打破循环依赖。
 */
class EventLoop;

class Channel : noncopyable
{
public:
    // 事件的回调函数
    using EventCallback = std::function<void()>;
    // 读事件的回调函数
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop *loop, int fd);
    ~Channel();
    // fd得到poller通知以后处理事件(调用回调函数处理)
    void handleEvent(Timestamp receivTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

    // 防止当channel被手动remove掉，channel还在执行回调操作
    // 这种 tie 函数通常用于创建一个 std::weak_ptr，它指向 std::shared_ptr 所管理的对象，但不改变对象的引用计数。
    // 这样，你可以在 std::weak_ptr 的生命周期内监测 std::shared_ptr 是否仍然存在，而不影响 std::shared_ptr 的生命周期。
    // unique_ptr和shared_ptr是强智能指针，weak_ptr是弱智能指针
    void tie(const std::shared_ptr<void> &);
    int fd() const { return fd_; }
    int events() const { return events_; }
    void set_revents(int revt) { revents_ = revt; } // channer不能监听需要靠poller监听然后返回给channel

    // 设置fd相对应的事件状态，并通知epoll，类似于epoll_ctl
    void enableReading()
    {
        events_ |= kReadEvent;
        update();
    }
    void disableReading()
    {
        events_ &= ~kReadEvent;
        update();
    }
    void enableWriting()
    {
        events_ |= kWriteEvent;
        update();
    }
    void disableWriting()
    {
        events_ &= ~kWriteEvent;
        update();
    }
    void disableAll()
    {
        events_ = kNoneEvent;
        update();
    }

    // 返回fd当前的事件状态
    bool isNoneEvent() const { return events_ == kNoneEvent; }
    bool isWriting() const { return events_ & kWriteEvent; }
    bool isReading() const { return events_ & kReadEvent; }

    int index() { return index_; }
    void set_index(int idx) { index_ = idx; }

    // one loop per thread
    // 当前channel属于哪个EventLoop
    EventLoop *ownerLoop() { return loop_; }
    // 删除channel
    void remove();

private:
    void update();
    void handleEventWithGuard(Timestamp receivTime);

    static const int kNoneEvent;  // fd不对任何事件感兴趣
    static const int kReadEvent;  // fd对读事件感兴趣
    static const int kWriteEvent; // fd对写事件感兴趣

    EventLoop *loop_; // 事件循环
    const int fd_;    // fd,Poller监听的对象
    int events_;      // 注册fd感兴趣的事件
    int revents_;     // Poller返回的具体发生的事件
    int index_;

    // 声明了一个 std::weak_ptr 类型的变量 tie_，它可以指向任何类型的对象（因为它是指向 void 类型的），
    std::weak_ptr<void> tie_; // 监听跨线程的对象的生存状态
    bool tied_;

    // 因为Channel通道里面能够获知fd最终发生的具体事件revents,所以它负责调用具体事件的回调操作
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};